package server

import (
	"context"
	"log"
	"sync"
)

// RoomClient 表示在房间中的客户端
type RoomClient struct {
	client *Client
	room   *Room
	ctx    context.Context
	cancel context.CancelFunc
	id     string
}

// NewRoomClient 创建一个新的房间客户端
func NewRoomClient(client *Client, room *Room) *RoomClient {
	ctx, cancel := context.WithCancel(context.Background())
	rc := &RoomClient{
		client: client,
		room:   room,
		ctx:    ctx,
		cancel: cancel,
		id:     client.id,
	}

	// 订阅房间事件
	room.eventBus.Subscribe(EventClientJoin, client.id, rc)
	room.eventBus.Subscribe(EventClientLeave, client.id, rc)
	room.eventBus.Subscribe(EventMsgBroadcast, client.id, rc)
	room.eventBus.Subscribe(EventChangePlayFile, client.id, rc)
	room.eventBus.Subscribe(EventChangePlayState, client.id, rc)
	room.eventBus.Subscribe(EventObjSync, client.id, rc)
	room.eventBus.Subscribe(EventRoomOwnerChange, client.id, rc)
	room.eventBus.Subscribe(EventRoomOwnerRequest, client.id, rc)
	room.eventBus.Subscribe(EventRoomProgress, client.id, rc)
	room.eventBus.Subscribe(EventMultiObjSync, client.id, rc)
	return rc
}

// HandleEvent 实现EventListener接口
func (rc *RoomClient) HandleEvent(ctx context.Context, event Event) {
	// 检查上下文是否已取消
	select {
	case <-ctx.Done():
		return
	case <-rc.ctx.Done():
		return
	default:
		// 继续处理
	}

	switch event.Type {
	case EventClientJoin:
		rc.handleClientJoin(event)
	case EventClientLeave:
		rc.handleClientLeave(event)
	case EventMsgBroadcast:
		rc.handleMsgBroadcast(event)
	case EventChangePlayFile:
		rc.handleChangePlayFile(event)
	case EventChangePlayState:
		rc.handleChangePlayState(event)
	case EventObjSync:
		rc.handleObjSync(event)
	case EventRoomOwnerChange:
		rc.handleRoomOwnerChange(event)
	case EventRoomOwnerRequest:
		rc.handleRoomOwnerRequest(event)
	case EventRoomProgress:
		rc.handleRoomProgress(event)
	case EventMultiObjSync:
		rc.handleMultiObjSync(event)
	}
}

// handleClientJoin 处理客户端加入事件
func (rc *RoomClient) handleClientJoin(event Event) {
	clientID, ok := event.Data.(string)
	if !ok {
		return
	}

	// 如果是自己，发送所有已经进入房间的ID到自己客户端
	if clientID == rc.client.id {
		for _, roomClient := range rc.room.clients {
			data := NetData{
				Cmd:  int(RoomJoinRoom),
				Data: roomClient.client.id,
			}
			rc.client.Send(data)
		}
		return
	}

	// 通知有新客户端加入
	data := NetData{
		Cmd:  int(RoomJoinRoom),
		Data: clientID,
	}
	rc.client.Send(data)
}

// handleClientLeave 处理客户端离开事件
func (rc *RoomClient) handleClientLeave(event Event) {
	clientID, ok := event.Data.(string)
	if !ok {
		return
	}

	if clientID != rc.client.id {
		data := NetData{
			Cmd:  int(RoomLeaveRoom),
			Data: clientID,
		}
		rc.client.Send(data)
	}
}

// handleMsgBroadcast 处理消息广播事件
func (rc *RoomClient) handleMsgBroadcast(event Event) {
	// 根据需要实现
}

// handleChangePlayFile 处理播放文件变更事件
func (rc *RoomClient) handleChangePlayFile(event Event) {
	fileID, ok := event.Data.(string)
	if !ok {
		return
	}

	data := NetData{
		Cmd:  int(RoomChangePlayRoomFile),
		Data: fileID,
	}
	rc.client.Send(data)
}

// handleChangePlayState 处理播放状态变更事件
func (rc *RoomClient) handleChangePlayState(event Event) {
	stateCmd, ok := event.Data.(string)
	if !ok {
		return
	}

	data := NetData{
		Cmd:  int(RoomChangePlayState),
		Data: stateCmd,
	}
	rc.client.Send(data)
}

// handleObjSync 处理对象同步事件
func (rc *RoomClient) handleObjSync(event Event) {
	info, ok := event.Data.(string)
	if !ok {
		return
	}

	data := NetData{
		Cmd:  int(RoomObjSynchronization),
		Data: info,
	}
	rc.client.Send(data)
}

// handleMultiObjSync 处理多对象同步事件
func (rc *RoomClient) handleMultiObjSync(event Event) {
	info, ok := event.Data.(string)
	if !ok {
		return
	}

	data := NetData{
		Cmd:  int(RoomMultiObjSync),
		Data: info,
	}
	rc.client.Send(data)
}

// handleRoomOwnerChange 处理房主变更事件
func (rc *RoomClient) handleRoomOwnerChange(event Event) {
	ownerID, ok := event.Data.(string)
	if !ok {
		return
	}

	data := NetData{
		Cmd:  int(RoomRoomOwnerChange),
		Data: ownerID,
	}
	rc.client.Send(data)
}

// handleRoomOwnerRequest 处理房主请求事件
func (rc *RoomClient) handleRoomOwnerRequest(event Event) {
	requestorID, ok := event.Data.(string)
	if !ok {
		return
	}

	// 只有当前房主才会收到这个事件
	if rc.client.id == rc.room.roomOwner.client.id {
		data := NetData{
			Cmd:  int(RoomRequestRoomOwner),
			Data: requestorID,
		}
		rc.client.Send(data)
	}
}

func (rc *RoomClient) handleRoomProgress(event Event) {
	d, ok := event.Data.(string)
	if !ok {
		return
	}

	data := NetData{
		Cmd:  int(RoomSyncRoomPlayProgress),
		Data: d,
	}
	rc.client.Send(data)
}

// LeaveRoom 离开房间
func (rc *RoomClient) LeaveRoom() {
	// 取消所有事件订阅
	rc.room.eventBus.UnsubscribeAll(rc.client.id)

	// 取消上下文
	rc.cancel()

	// 发送离开房间消息
	data := NetData{
		Cmd:  int(RoomLeaveRoom),
		Data: rc.client.id,
	}
	rc.client.Send(data)

	// 从房间移除
	rc.room.removeClient(rc)
}

// Room 表示一个房间
type Room struct {
	roomName         string
	clients          []*RoomClient
	roomOwner        *RoomClient
	waitingRoomOwner *RoomClient
	mu               sync.RWMutex
	eventBus         *EventBus
	ctx              context.Context
	cancel           context.CancelFunc
	onEmpty          func(roomName string) // 当房间为空时调用的回调
}

// NewRoom 创建一个新的房间
func NewRoom(name string, onEmpty func(roomName string)) *Room {
	ctx, cancel := context.WithCancel(context.Background())
	return &Room{
		roomName: name,
		clients:  make([]*RoomClient, 0),
		eventBus: NewEventBus(),
		ctx:      ctx,
		cancel:   cancel,
		onEmpty:  onEmpty,
	}
}

// JoinRoom 客户端加入房间
func (r *Room) JoinRoom(client *RoomClient) {
	r.mu.Lock()
	defer r.mu.Unlock()

	for _, v := range r.clients {
		if v.client.id == client.client.id {
			// 客户端已在房间中
			log.Printf("Room %s: client %s already in room", r.roomName, client.client.id)
			return
		}
	}
	r.clients = append(r.clients, client)

	// 如果是第一个客户端，设为房主
	if len(r.clients) == 1 {
		r.roomOwner = client
		r.ChangeRoomOwner(client)
	}

	// 发布客户端加入事件
	r.eventBus.Publish(Event{
		Type:   EventClientJoin,
		Data:   client.client.id,
		RoomID: r.roomName,
		Source: client.client.id,
	})

	log.Printf("Room %s: client %s joined, total clients: %d", r.roomName, client.client.id, len(r.clients))
}

// removeClient 从房间中移除客户端
func (r *Room) removeClient(client *RoomClient) {
	r.mu.Lock()
	defer r.mu.Unlock()

	// 从客户端列表中移除
	for i, c := range r.clients {
		if c.client.id == client.client.id {
			r.clients = append(r.clients[:i], r.clients[i+1:]...)
			break
		}
	}

	// 发布客户端离开事件
	r.eventBus.Publish(Event{
		Type:   EventClientLeave,
		Data:   client.client.id,
		RoomID: r.roomName,
		Source: client.client.id,
	})

	// 如果只剩一个客户端，设为房主
	if len(r.clients) == 1 {
		r.roomOwner = r.clients[0]
		r.ChangeRoomOwner(r.roomOwner)
	} else if len(r.clients) == 0 {
		r.roomOwner = nil
		// 房间为空，关闭事件总线
		r.Close()

		// 调用回调通知房间已空
		if r.onEmpty != nil {
			r.onEmpty(r.roomName)
		}
	}

	log.Printf("Room %s: client %s left, total clients: %d", r.roomName, client.client.id, len(r.clients))
}

// RoomOwnerRequest 请求成为房主
func (r *Room) RoomOwnerRequest(client *RoomClient) {
	r.mu.Lock()
	defer r.mu.Unlock()

	if r.roomOwner != nil && client.client.id == r.roomOwner.client.id {
		// 自己请求无效
		return
	}

	r.waitingRoomOwner = client

	// 发布房主请求事件
	r.eventBus.Publish(Event{
		Type:   EventRoomOwnerRequest,
		Data:   client.client.id,
		RoomID: r.roomName,
		Source: client.client.id,
	})
}

// ResponceOwner 房主响应转移请求
func (r *Room) ResponceOwner(result string) {
	r.mu.Lock()
	defer r.mu.Unlock()

	if result == "0" {
		r.waitingRoomOwner = nil
	} else if result == "1" && r.waitingRoomOwner != nil {
		r.ChangeRoomOwner(r.waitingRoomOwner)
		r.waitingRoomOwner = nil
	}
}

// ChangeRoomOwner 更改房主
func (r *Room) ChangeRoomOwner(newOwnerClient *RoomClient) {
	r.roomOwner = newOwnerClient

	// 发布房主变更事件
	r.eventBus.Publish(Event{
		Type:   EventRoomOwnerChange,
		Data:   newOwnerClient.client.id,
		RoomID: r.roomName,
		Source: newOwnerClient.client.id,
	})
}

// ChangePlayFile 更改播放文件
func (r *Room) ChangePlayFile(id string) {
	r.eventBus.Publish(Event{
		Type:   EventChangePlayFile,
		Data:   id,
		RoomID: r.roomName,
		Source: r.roomOwner.client.id,
	})
}

// ChangePlayState 更改播放状态
func (r *Room) ChangePlayState(stateCmd string) {
	r.eventBus.Publish(Event{
		Type:   EventChangePlayState,
		Data:   stateCmd,
		RoomID: r.roomName,
		Source: r.roomOwner.client.id,
	})
}

// RoomObjSynchronization 对象同步
func (r *Room) RoomObjSynchronization(info string) {
	r.eventBus.Publish(Event{
		Type:   EventObjSync,
		Data:   info,
		RoomID: r.roomName,
		Source: r.roomOwner.client.id,
	})
}

// PushRoomPlayProgress 响应播放进度
func (r *Room) PushRoomPlayProgress(data string) {
	r.eventBus.Publish(Event{
		Type:   EventRoomProgress,
		Data:   data,
		RoomID: r.roomName,
		Source: r.roomOwner.client.id,
	})
}

// GetRoomPlayProgress 获取房间播放进度（通知房主同步一次播放进度）
func (r *Room) GetRoomPlayProgress(data string) {
	// 如果房主不存在，则返回
	if r.roomOwner == nil {
		return
	}

	// 向房主发送获取播放进度请求
	ownerData := NetData{
		Cmd:  int(RoomGetRoomPlayProgress),
		Data: data,
	}
	r.roomOwner.client.Send(ownerData)
}

// RoomMultiObjSync 多对象同步
func (r *Room) RoomMultiObjSync(data string) {
	r.eventBus.Publish(Event{
		Type:   EventMultiObjSync,
		Data:   data,
		RoomID: r.roomName,
		Source: r.roomOwner.client.id,
	})
}

// BecomeOwner 直接成为房主，并推送给所有人
func (r *Room) BecomeOwner(newOwnerClient *RoomClient, data string) {
	r.mu.Lock()
	defer r.mu.Unlock()

	if data == "" {
		return
	} else {
		r.ChangeRoomOwner(newOwnerClient)
		r.waitingRoomOwner = nil
	}
}

// GetRoomCount 获取房间人数
func (r *Room) GetRoomCount() int {
	r.mu.RLock()
	defer r.mu.RUnlock()
	return len(r.clients)
}

// Close 关闭房间，清理资源
func (r *Room) Close() {
	r.cancel()
	r.eventBus.Close()
}
